package com.phychips.rcp;

import com.phychips.common.*;
import com.phychips.common.ReaderIo.logType;

import android.util.Log;

public class RcpResponse {
    public enum targetType {
        PR9000, PR9200
    }

    private targetType mTarget = null;
    final int ADC_ARRAY_LEN = 10;
    final int ADC_INIT = -1;
    int[] adcArray = new int[ADC_ARRAY_LEN];

    public RcpResponse(targetType target) {
        mTarget = target;
        adcArray[0] = ADC_INIT;
    }

    public OnBytesAvailableListener getOnBytesAvailableListener() {
        return mListener;
    } // End OnBytesAvailableListener()

    public iRcpEvent2 mRcpEvent2 = null;

    public void setRcpEvent(iRcpEvent2 e) {
        mRcpEvent2 = e;
    }

    private int getPcEpcLength(int pcMsb) {
        int length = ((pcMsb >> 2) & 0xFE) + 2;

        return length;
    }

    public void parse9200RxData(int[] rcv) {
        int paylord_length = (((int) rcv[3] & 0xff) << 8)
                | ((int) rcv[4] & 0xff);
        byte cmd = (byte) rcv[2];

        int[] dest = new int[paylord_length];
        System.arraycopy(rcv, 5, dest, 0, paylord_length);

        switch (cmd) {
            case RcpConst.RCP_CMD_GET_RD_INFO:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onReaderInfoReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_UII:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onTagReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_UII_TID:
                if (mRcpEvent2 != null) {
                    //if(dest[0]==0x00) break;
                    if (dest.length == 1) break;

                    int pcEpcLength = getPcEpcLength(dest[0]);

                    int[] pcEpc = new int[pcEpcLength];
                    int[] tid = new int[dest.length - pcEpcLength];

                    System.arraycopy(dest, 0, pcEpc, 0, pcEpc.length);
                    System.arraycopy(dest, pcEpc.length, tid, 0, tid.length);

                    mRcpEvent2.onTagWithTidReceived(pcEpc, tid);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_EX2:
                if (mRcpEvent2 != null) {
                    System.out.println("1. dest = " + dest[0]);
                    if (dest.length < 3) break;

                    int offset = 3;
                    int pcEpcLength = getPcEpcLength(dest[offset]);

                    int[] pcEpc = new int[pcEpcLength];
                    int[] tid = new int[dest.length - pcEpcLength - offset];

                    System.arraycopy(dest, offset, pcEpc, 0, pcEpc.length);
                    System.arraycopy(dest, offset + pcEpc.length, tid, 0, tid.length);

                    mRcpEvent2.onTagWithTidReceived(pcEpc, tid);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_UII_RSSI: {
                int dataLen = paylord_length;
                int rssi_i = dest[dataLen - 4] & 0xff;
                int rssi_q = dest[dataLen - 3] & 0xff;
                int gain_i = dest[dataLen - 2] & 0xff;
                int gain_q = dest[dataLen - 1] & 0xff;

                double rfin_i = (20 * Math.log10(rssi_i) - gain_i - 33 - 30);
                double rfin_q = (20 * Math.log10(rssi_q) - gain_q - 33 - 30);

                rfin_i = Math.pow(10, (rfin_i / 20));
                rfin_q = Math.pow(10, (rfin_q / 20));

                final int rssi = (int) (20 * Math.log10(Math.sqrt(Math.pow(rfin_i,
                        2) + Math.pow(rfin_q, 2))));

                int[] newDest = new int[paylord_length - 4];
                System.arraycopy(dest, 0, newDest, 0, paylord_length - 4);

                if (mRcpEvent2 != null) {
                    mRcpEvent2.onTagWithRssiReceived(newDest, rssi);
                }
            }
            break;
            case RcpConst.RCP_CMD_AUTHENTICATE:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }

                break;
            case RcpConst.RCP_CMD_AUTHENTICATE_EX:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }

                break;
            case RcpConst.RCP_CMD_GET_REGION:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onRegionReceived(dest[0]);
                }
                break;
            case RcpConst.RCP_CMD_GET_C_SEL_PARAM:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSelectParamReceived(dest);
                }

                break;
            case RcpConst.RCP_CMD_GET_C_QRY_PARAM:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onQueryParamReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_GET_CH:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onChannelReceived(dest[0], dest[1]);
                }
                break;
            case RcpConst.RCP_CMD_GET_FH_LBT:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onFhLbtReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_GET_TX_PWR:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onTxPowerLevelReceived(dest[0]);
                }
                break;
            case RcpConst.RCP_CMD_GET_BEEP:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_DT:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onTagMemoryReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_GET_HOPPING_TBL:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_GET_MODULATION:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_GET_ANTICOL_MODE:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_GET_TEMPERATURE:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_GET_RSSI:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_GET_REGISTRY_ITEM:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_CTL_RESET:
                if (mRcpEvent2 != null) {
                    adcArray[0] = ADC_INIT;
                    mRcpEvent2.onResetReceived();
                }
                break;
            case RcpConst.RCP_BATTERY_RES: {
                int minLevel = 255;
                int maxLevel = 0;
                int sumLevel = 0;

                if (adcArray[0] == ADC_INIT) {
                    for (int i = 0; i < ADC_ARRAY_LEN; i++) {
                        adcArray[i] = dest[0] & 0xff;
                    }
                }

                for (int i = 0; i < ADC_ARRAY_LEN - 1; i++) {
                    adcArray[i] = adcArray[i + 1];
                    sumLevel += adcArray[i];
                }
                adcArray[ADC_ARRAY_LEN - 1] = dest[0] & 0xff;
                sumLevel += dest[0] & 0xff;

                for (int i = 0; i < ADC_ARRAY_LEN; i++) {
                    if (minLevel > adcArray[i])
                        minLevel = adcArray[i];
                    if (maxLevel < adcArray[i])
                        maxLevel = adcArray[i];
                }

                //System.out.println("dest" + dest[0] + "," + minLevel + "," + maxLevel);
                sumLevel -= minLevel;
                sumLevel -= maxLevel;
                sumLevel = sumLevel >> 3;

                dest[0] = sumLevel & 0xff;
                //System.out.println("dest" + dest[0] + "," + dest[1] + "," + dest[2]);

                if (mRcpEvent2 != null) {
                    mRcpEvent2.onBatteryStateReceived(dest);
                }
            }
            break;
            case RcpConst.RCP_CMD_FER_TEST:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.RCP_CMD_READ_C_DT_EX:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onTagMemoryLongReceived(dest);
                }
                break;
            case RcpConst.RCP_CMD_GET_SESSION:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSessionReceived(dest[0]);
                }
                break;
            case RcpConst.RCP_CMD_SET_BEEP:
            case RcpConst.RCP_CMD_STOP_AUTO_READ_EX:
            case RcpConst.RCP_CMD_SET_REGION:
            case RcpConst.RCP_CMD_SET_C_SEL_PARAM:
            case RcpConst.RCP_CMD_SET_C_QRY_PARAM:
            case RcpConst.RCP_CMD_SET_CH:
            case RcpConst.RCP_CMD_SET_FH_LBT:
            case RcpConst.RCP_CMD_SET_TX_PWR:
            case RcpConst.RCP_CMD_CTL_CW:
            case RcpConst.RCP_CMD_SET_HOPPING_TBL:
            case RcpConst.RCP_CMD_SET_MODULATION:
            case RcpConst.RCP_CMD_SET_ANTICOL_MODE:
            case RcpConst.RCP_CMD_WRITE_C_DT:
            case RcpConst.RCP_CMD_BLOCKERASE_C_DT:
            case RcpConst.RCP_CMD_BLOCKWRITE_C_DT:
            case RcpConst.RCP_CMD_UNTRACEABLE:
            case RcpConst.RCP_CMD_UNTRACEABLE_EX:
            case RcpConst.RCP_CMD_READSIGNATURE:
            case RcpConst.RCP_CMD_KILL_RECOM_C:
            case RcpConst.RCP_CMD_LOCK_C:
            case RcpConst.RCP_UPDATE_REGISTRY:
            case RcpConst.RCP_ERASE_REGISTRY:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
            case RcpConst.COMMAND_FAIL:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onFailureReceived(dest);
                }
                break;
            default:
                if (mRcpEvent2 != null) {
                    mRcpEvent2.onSuccessReceived(dest, cmd);
                }
                break;
        }
    }

    private OnBytesAvailableListener mListener = new OnBytesAvailableListener() {
        @Override
        public void onBytesAvailable(byte[] rxData) {
            int[] rcv = new int[rxData.length];

            for (int i = 0; i < rcv.length; i++) {
                byte temp = (Byte) rxData[i];
                rcv[i] = (int) temp;
            }

            if (mTarget != targetType.PR9000) {
                if (!RcpLib.Chk_CRC(rcv)) {
                    Log.i("RCPRsp", "crc_error");
                    return;
                }
            }

            try {
                ReaderIo.log_write(logType.RSP, rxData);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            switch (mTarget) {
                default:
                    parse9200RxData(rcv);
                    break;
            }
        }
    };
} // End class
